{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Repeat"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `repeat` concept of the QMOD language is just like a classical for loop but for quantum objects. That is, when one wants to repeat a quantum operation several times, e.g. to do a bit-wise operation, they can just use the `repeat` concept of QMOD. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the Classiq Python SDK package `repeat` is accessed as a function that has 2 arguments:\n",
    "\n",
    "1. `count`: `int` or `CInt` - how many times to repeat the operation;\n",
    "2. `iteration`: `QCallable` - what operation to repeat;\n",
    "\n",
    "The argmuent that is passed as the `iteration` is a function by itself. Therefore it leverages the concept of lambda functions in Python (read more [here](https://www.geeksforgeeks.org/python-lambda-anonymous-functions-filter-map-reduce/))."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the following example, two quantum states $|\\psi \\rangle$ and $| \\phi \\rangle$ are initialized with 5 qubits each. Then an Hadamard gate is applied on all the qubits of $|\\psi \\rangle$, i.e. $H^{\\otimes 5}|\\psi \\rangle$, and a NOT gate on all the qubits of $|\\phi \\rangle$, i.e. $X^{\\otimes 5}|\\phi \\rangle$.\n",
    "Finally, using the `repeat` function, a bit-wise `SWAP` is performed between $|\\phi \\rangle$ and $|\\psi \\rangle$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-align:center;\">\n",
    "    <img src=\"https://docs.classiq.io/resources/repeat_example.gif\" alt=\"Phase Kickback High Level\" />\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:38.382860Z",
     "iopub.status.busy": "2024-05-07T13:27:38.382455Z",
     "iopub.status.idle": "2024-05-07T13:27:43.966940Z",
     "shell.execute_reply": "2024-05-07T13:27:43.966176Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opening: https://platform.classiq.io/circuit/5b8e48b5-93c5-4068-8ce7-3ba10b2a814b?version=0.41.0.dev39%2B79c8fd0855\n"
     ]
    }
   ],
   "source": [
    "from classiq import (\n",
    "    SWAP,\n",
    "    H,\n",
    "    Output,\n",
    "    QArray,\n",
    "    QBit,\n",
    "    X,\n",
    "    allocate,\n",
    "    apply_to_all,\n",
    "    create_model,\n",
    "    qfunc,\n",
    "    repeat,\n",
    "    show,\n",
    "    synthesize,\n",
    ")\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def main(psi: Output[QArray[QBit]], phi: Output[QArray[QBit]]):\n",
    "\n",
    "    allocate(num_qubits=5, out=psi)\n",
    "    allocate(num_qubits=5, out=phi)\n",
    "\n",
    "    apply_to_all(H, psi)\n",
    "    apply_to_all(X, phi)\n",
    "\n",
    "    repeat(count=psi.len, iteration=lambda i: SWAP(phi[i], psi[i]))\n",
    "\n",
    "\n",
    "qprog = synthesize(create_model(main))\n",
    "show(qprog)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The native QMOD version of the above code:\n",
    "\n",
    "```\n",
    "// Repeat Example\n",
    "\n",
    "qfunc main(output psi: qbit[], output phi: qbit[]) {\n",
    "  allocate<5>(psi);\n",
    "  allocate<5>(phi);\n",
    "  \n",
    "  apply_to_all<H>(psi);\n",
    "  apply_to_all<X>(phi);\n",
    "  \n",
    "  repeat(i:psi.len) {\n",
    "    SWAP(phi[i], psi[i]);\n",
    "  }\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:44.032537Z",
     "iopub.status.busy": "2024-05-07T13:27:44.031909Z",
     "iopub.status.idle": "2024-05-07T13:27:44.053963Z",
     "shell.execute_reply": "2024-05-07T13:27:44.053172Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import write_qmod\n",
    "\n",
    "write_qmod(create_model(main), \"repeat\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.11.7 ('classiq_devolpment')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  },
  "vscode": {
   "interpreter": {
    "hash": "e992e515f6583afc67b46eeabcda0f30363069fab8b382c7517b274ba7a59477"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
